package com.utils.tfzf;

import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.Log4JLoggerFactory;

public class Api {
	static InternalLogger log = Log4JLoggerFactory.getInstance(Api.class);
	private static final String MERCHANT_APPLY = "http://tianfu.juliye.com/payment/merchant/apply";
	private static final String QUERY_PARTNER_FEE = "http://tianfu.juliye.com/payment/partner/fee";
	private static final String DYNAMIC_PAY_PRE_CREATE = "http://tianfu.juliye.com/payment/dynamic/pay";
	private static final String MERGE_PAY = "http://tianfu.juliye.com/payment/merge/pay";
	private static final String QUERY_ORDER = "http://tianfu.juliye.com/payment/order/detail";
	private static final String CLOSE_ORDER = "http://tianfu.juliye.com/payment/close/order";
	private static final String QUERY_MEMBER_BALANCE = "http://tianfu.juliye.com/payment/member/balance";
	private static final String WITHDRAW = "http://tianfu.juliye.com/payment/withdraw";
	private static final String WITHDRAW_QUERY = "http://tianfu.juliye.com/payment/withdraw/detail";
	private static final String QUERY_MEMBER_ACCOUNT_DETAILS = "http://tianfu.juliye.com/payment/member/account/detail";
	private static final String DOWNLOAD_ACCOUNT_STATEMENT = "http://tianfu.juliye.com/payment/down/account/statement";
	private static final String QUERY_BILL_LIST = "http://tianfu.juliye.com/payment/billing/list";

	/**
	 * 特约商户注册和入驻申请<br/>
	 * 说明：<br/>
	 * 1.此接口仅用于新特约商户入驻，或特约商户入驻申请被拒绝之后，修改资料重新提交更改<br/>
	 * 2.此接口不能用作商户信息修改，商户信息修改请调用《特约商户基本信息修改申请》接口<br/>
	 * 3.当结算户为个人结算户时，开户网点号与结算户银行号无需上送，系统直接根据卡号通过卡Bin自动查询这两个数据入库<br/>
	 * 4.当结算户为对公结算户时，开户网点号与结算户银行号必传
	 * 5.接口正常响应所返回的custId是商户ID，前边拼上120即是商户号，例如接口返回custId为2844777，则该商户的商户号（subpartner）为1202844777
	 * @param params 接口请求参数
	 */
	public static Kv custApply(Kv params) {
		//发起请求
		JSONObject result = post(MERCHANT_APPLY, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("custId",result.getByPath("object.custId",String.class))
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 商户通道费率查询，通过该接口可查询商户已开通支付子产品和子产品通道费率
	 * @param params 接口请求参数
	 */
	public static Kv queryPartnerFee(Kv params) {
		//发起请求
		JSONObject result = get(QUERY_PARTNER_FEE, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("listMerchantPassageway",result.getByPath("object.listMerchantPassageway",JSONArray.class))
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 动态一码付
	 * @param params 接口请求参数
	 */
	public static Kv dynamicPayPreCreate(Kv params) {
		//发起请求
		JSONObject result = post(DYNAMIC_PAY_PRE_CREATE, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("outTradeNo",result.getByPath("object.outTradeNo",String.class))
						.set("qrCode",result.getByPath("object.qrCode",String.class))
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 聚合支付
	 * @param params 接口请求参数
	 */
	public static Kv mergePay(Kv params) {
		//发起请求
		JSONObject result = post(MERGE_PAY, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				//1.取基础参数
				Kv kv = Kv.create().set("status",true)
						.set("tradeState",result.getByPath("object.tradeState",String.class))
						.set("transactionId",result.getByPath("object.transactionId",String.class))
						.set("attach",result.getByPath("object.attach",String.class))
						.set("timeEnd",result.getByPath("object.timeEnd",String.class))
						.set("payTransNo",result.getByPath("object.payTransNo",String.class))
						.set("bankType",result.getByPath("object.bankType",String.class))
						.set("transChannel",result.getByPath("object.transChannel",String.class))
						.set("returnMsg",result.getByPath("object.returnMsg",String.class))
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
				//2.取非公共参数，以下将根据支付渠道来取值
				String transChannel = params.getStr("transChannel");
				if(transChannel.equals("alipay_qr_pup")){
					//支付渠道为支付宝服务窗模式（一码付）时
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",result.getByPath("object.aliPayOrWeChat.code",String.class))
						.set("qrCode",result.getByPath("object.aliPayOrWeChat.qrCode",String.class))
					);
				}else if(transChannel.equals("alipay_qr_a")){
					//支付渠道为支付宝当面付(被扫)(条码支付)时
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",result.getByPath("object.aliPayOrWeChat.code",String.class))
						.set("buyerId",result.getByPath("object.aliPayOrWeChat.buyerId",String.class))
						.set("externalId",result.getByPath("object.aliPayOrWeChat.externalId",String.class))
					);
				}else if(transChannel.equals("alipay_qr_p")){
					//支付渠道为支付宝当面付(主扫)(扫码支付)时
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",result.getByPath("object.aliPayOrWeChat.code",String.class))
						.set("qrCode",result.getByPath("object.aliPayOrWeChat.qrCode",String.class))
					);
				}else if(transChannel.equals("wx_pub")){
					//支付渠道为微信公众号支付(一码付)时
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",result.getByPath("object.aliPayOrWeChat.code",String.class))
						//此时qrCode值格式例如：appId=XXXX&timeStamp=XXXX&nonceStr=XXXXX&package=prepay_id=XXXXX&signType=MD5&paySign=XXXXX
						.set("qrCode",result.getByPath("object.aliPayOrWeChat.qrCode",String.class))
					);
				}else if(transChannel.equals("wx_lite")){
					//支付渠道为微信小程序支付时
					String returnMsg = result.getByPath("object.returnMsg",String.class);
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",null)
						.set("qrCode",JSONUtil.parseObj(returnMsg).getByPath("qr_code",String.class))
					);
				}else if(transChannel.equals("wx_qr_p")){
					//支付渠道为微信扫码支付(主扫)时
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",result.getByPath("object.aliPayOrWeChat.code",String.class))
						.set("qrCode",result.getByPath("object.aliPayOrWeChat.qrCode",String.class))
					);
				}else if(transChannel.equals("wx_qr_a")){
					//支付渠道为微信刷卡支付(被扫)时
					kv.set("aliPayOrWeChat",Kv.create()
						.set("code",result.getByPath("object.aliPayOrWeChat.code",String.class))
						.set("buyerId",result.getByPath("object.aliPayOrWeChat.buyerId",String.class))
						.set("externalId",result.getByPath("object.aliPayOrWeChat.externalId",String.class))
						.set("bankType",result.getByPath("object.aliPayOrWeChat.bankType",String.class))
						.set("promotionDetail",result.getByPath("object.aliPayOrWeChat.promotionDetail",String.class))
					);
				}
				return kv;
			}
		});
	}
	
	/**
	 * 订单查询
	 * @param params 接口请求参数
	 */
	public static Kv queryOrder(Kv params) {
		//发起请求
		JSONObject result = get(QUERY_ORDER, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("tradeState",result.getByPath("object.tradeState",String.class))
						.set("refundState",result.getByPath("object.refundState",String.class))
						.set("clearState",result.getByPath("object.clearState",String.class))
						.set("tradeMode",result.getByPath("object.tradeMode",String.class))
						.set("tradeType",result.getByPath("object.tradeType",String.class))
						.set("bankTransNo",result.getByPath("object.bankTransNo",String.class))
						.set("totalFee",result.getByPath("object.totalFee",String.class))
						.set("feeType",result.getByPath("object.feeType",String.class))
						.set("outTradeNo",result.getByPath("object.outTradeNo",String.class))
						.set("outRefundNo",result.getByPath("object.outRefundNo",String.class))
						.set("transactionId",result.getByPath("object.transactionId",String.class))
						.set("isSplit",result.getByPath("object.isSplit",String.class))
						.set("timeEnd",result.getByPath("object.timeEnd",String.class))
						.set("transportFee",result.getByPath("object.transportFee",String.class))
						.set("platCharge",result.getByPath("object.platCharge",String.class))
						.set("subPlatCharge",result.getByPath("object.subPlatCharge",String.class))
						.set("productFee",result.getByPath("object.productFee",String.class))
						.set("discount",result.getByPath("object.discount",String.class))
						.set("attach",result.getByPath("object.attach",String.class))
						.set("buyerLoginId",result.getByPath("object.buyerLoginId",String.class))
						.set("buyerUserid",result.getByPath("object.buyerUserid",String.class))
						.set("bankCode",result.getByPath("object.bankCode",String.class))
						.set("openid",result.getByPath("object.openid",String.class))
						.set("subOpenId",result.getByPath("object.subOpenId",String.class))
						.set("promotionDetail",result.getByPath("object.promotionDetail",String.class))
						.set("transChannel",result.getByPath("object.transChannel",String.class))
						.set("payTransNo",result.getByPath("object.payTransNo",String.class))
						.set("bankType",result.getByPath("object.bankType",String.class))
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 订单关闭
	 * @param params 接口请求参数
	 */
	public static Kv closeOrder(Kv params) {
		//发起请求
		JSONObject result = post(CLOSE_ORDER, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("partner",result.getByPath("object.partner",String.class))
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("transactionId",result.getByPath("object.transactionId",String.class))
						.set("outTradeNo",result.getByPath("object.outTradeNo",String.class))
						.set("closeState",result.getByPath("object.closeState",String.class))
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 余额与待清算金额查询
	 * @param params 接口请求参数
	 */
	public static Kv queryMemberBalance(Kv params) {
		//发起请求
		JSONObject result = get(QUERY_MEMBER_BALANCE, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("blance",result.getByPath("object.blance",String.class))//余额
						.set("unClearingAmt",result.getByPath("object.unClearingAmt",String.class))//待清算余额
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 提现
	 * @param params 接口请求参数
	 */
	public static Kv withdraw(Kv params) {
		//发起请求
		JSONObject result = post(WITHDRAW, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("transAmount",result.getByPath("object.transAmount",String.class))//提现金额
						.set("transactionId",result.getByPath("object.transactionId",String.class))//交易流水
						.set("charge",result.getByPath("object.charge",String.class))//手续费
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 提现查询
	 * @param params 接口请求参数
	 */
	public static Kv withdrawQuery(Kv params) {
		//发起请求
		JSONObject result = get(WITHDRAW_QUERY, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("transAmount",result.getByPath("object.transAmount",String.class))//提现金额
						.set("transactionId",result.getByPath("object.transactionId",String.class))//交易流水
						.set("transState",result.getByPath("object.transState",String.class))//交易状态，0-待受理，1-处理中，2-成功，5-失败
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 资金变动明细查询
	 * @param params 接口请求参数
	 */
	public static Kv queryMemberAccountDetails(Kv params) {
		//发起请求
		JSONObject result = get(QUERY_MEMBER_ACCOUNT_DETAILS, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				Kv kv = Kv.create().set("status",true)
						.set("totalRec",result.getByPath("object.totalRec",String.class))//总条数
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
				List<Kv> fundsChangeList = new ArrayList<Kv>();
				JSONArray jsonArray = (JSONArray)result.getByPath("object.fundsChangeList");
				for(Object jsonObject : jsonArray){
					JSONObject item = (JSONObject)jsonObject;
					fundsChangeList.add(Kv.create()
								.set("balance",item.getByPath("balance",String.class))
								.set("currencyType",item.getByPath("currencyType",String.class))
								.set("custno",item.getByPath("custno",String.class))
								.set("transAmount",item.getByPath("transAmount",String.class))
								.set("transDate",item.getByPath("transDate",String.class))
								.set("transName",item.getByPath("transName",String.class))
								.set("transTime",item.getByPath("transTime",String.class))
								.set("transTypeFlag",item.getByPath("transTypeFlag",String.class))
								.set("transno",item.getByPath("transno",String.class)));
				}
				kv.set("fundsChangeList",fundsChangeList);
				return kv;
			}
		});
	}
	
	/**
	 * 结算信息汇总查询
	 * @param params 接口请求参数
	 */
	public static Kv queryBillingList(Kv params) {
		//发起请求
		JSONObject result = get(QUERY_BILL_LIST, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				Kv kv = Kv.create().set("status",true)
						.set("subpartner",result.getByPath("object.subpartner",String.class))
						.set("totalRec",result.getByPath("object.totalRec",String.class))//总条数
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
				List<Kv> list = new ArrayList<Kv>();
				JSONArray jsonArray = (JSONArray)result.getByPath("object.list");
				for(Object jsonObject : jsonArray){
					JSONObject item = (JSONObject)jsonObject;
					list.add(Kv.create()
								.set("clearingAmount",item.getByPath("clearingAmount",String.class))
								.set("clearingBatchNo",item.getByPath("clearingBatchNo",String.class))
								.set("clearingCharge",item.getByPath("clearingCharge",String.class))
								.set("clearingCount",item.getByPath("clearingCount",Integer.class))
								.set("totalFee",item.getByPath("totalFee",String.class))
								.set("workDate",item.getByPath("workDate",String.class)));
				}
				kv.set("list",list);
				return kv;
			}
		});
	}
	
	/**
	 * 对帐单下载
	 * @param params 接口请求参数
	 */
	public static Kv downloadAccountStatement(Kv params) {
		//发起请求
		JSONObject result = get(DOWNLOAD_ACCOUNT_STATEMENT, params);
		//解析结果
		return onResult(result,new OnResultHandler() {
			@Override
			public Kv onSuccess(JSONObject result) {
				return Kv.create().set("status",true)
						.set("base64file",result.getByPath("object.base64file",String.class))
						.set("orderCount",result.getByPath("object.orderCount",Integer.class))
						.set("orderDate",result.getByPath("object.orderDate",String.class))
						.set("orderMoney",result.getByPath("object.orderMoney",String.class))
						.set("orderType",result.getByPath("object.orderType",String.class))//订单类型，0001-返回当日所有订单，0002-返回当日成功支付的订单，0003-返回当日退款的订单
						.set("returnSerNo",result.getByPath("object.returnSerNo",String.class));
			}
		});
	}
	
	/**
	 * 处理回调抽象类
	 * @author duxikun
	 */
	static abstract class OnResultHandler {
		public boolean isSuccess(JSONObject result){
			int status = Integer.valueOf(String.valueOf(result.get("status")));
			String code = String.valueOf(result.get("code"));
			return status==1&&code.equals("0200");
		}
		public abstract Kv onSuccess(JSONObject result);
		public Kv onFail(JSONObject result){
			String code = String.valueOf(result.get("code"));
			String message = result.getByPath("message",String.class);
			JSONArray errorDetails = result.getByPath("errorDetails",JSONArray.class);
			if(errorDetails!=null){
				log.debug("响应明细：" + message);
				for(Object object : errorDetails){
					JSONObject errorDetail = ((JSONObject)object);
					String errorMessage = errorDetail.getByPath("errorMessage",String.class);
					String errorField = errorDetail.getByPath("errorField",String.class);
	//				String errorValue = errorDetail.getByPath("errorValue",String.class);
					log.debug("[" + errorField + "][" + errorMessage + "]");
				}
			}
			return Kv.create().set("status",false).set("code",code).set("message",message).setIfNotNull("errorDetails",errorDetails);
		}
	}

	
	/**
	 * 解析响应结果
	 * @param result 响应结果
	 * @param handler 处理回调
	 */
	static Kv onResult(JSONObject result, OnResultHandler handler) {
		//解析结果验证成功或失败
		if(handler.isSuccess(result)){
			//成功
			return handler.onSuccess(result);
		}else{
			//失败
			return handler.onFail(result);
		}
	}
	
	/**
	 * 发起POST请求
	 * @param url 请求地址
	 * @param params 请求参数
	 */
	static JSONObject post(String url, Kv params) {
		log.debug("请求地址：" + url);
		log.debug("请求参数：" + params.toJson());
		try {
			HttpResponse response = HttpRequest.post(url).body(params.toJson()).execute();
			if(StrUtil.isNotBlank(response.body())){
				log.debug("响应结果：" + response.body());
				return JSONUtil.parseObj(response.body());
			}
			log.debug("请求失败，状态码：" + response.getStatus());
			return new JSONObject().set("status", 0).set("code", "0404").set("message", "请求失败，状态码：" + response.getStatus());
		} catch (Exception e) {
//			e.printStackTrace();
			return new JSONObject().set("status", 0).set("code", "0404").set("message", e.getLocalizedMessage());
		}
	}
	
	/**
	 * 发起GET请求
	 * @param url 请求地址
	 * @param params 请求参数
	 */
	@SuppressWarnings("unchecked")
	static JSONObject get(String url, Kv params) {
		log.debug("请求地址：" + url);
		log.debug("请求参数：" + params.toJson());
		try {
			HttpResponse response = HttpRequest.get(url).form(params).execute();
			if(StrUtil.isNotBlank(response.body())){
				log.debug("响应结果：" + response.body());
				return JSONUtil.parseObj(response.body());
			}
			log.debug("请求失败，状态码：" + response.getStatus());
			return new JSONObject().set("status", 0).set("code", "0404").set("message", "请求失败，状态码：" + response.getStatus());
		} catch (Exception e) {
//			e.printStackTrace();
			return new JSONObject().set("status", 0).set("code", "0404").set("message", e.getLocalizedMessage());
		}
	}
}
